/*
* Copyright (C) Microsoft. All rights reserved.  
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License.  You may obtain a copy 
* of the License at http://www.apache.org/licenses/LICENSE-2.0  
* 
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
* MERCHANTABLITY OR NON-INFRINGEMENT. 
*
* See the Apache License, Version 2.0 for specific language governing 
* permissions and limitations under the License.
*
*/
#pragma once

#include <baja/graphics/graphics_types.hpp>
#include <baja/graphics/graphics_interfaces.hpp>

namespace baja { namespace graphics {

namespace g = baja::graphics;

struct render_target
{
public:
    render_target() {}

    render_target(
        const viewport& viewport,
        const std::shared_ptr<isurface>& renderTarget,
        const std::shared_ptr<isurface>& depthStencilTarget
        ) : _viewport(viewport), _renderTarget(renderTarget), _depthStencilTarget(depthStencilTarget)
    {}

    void apply(const std::shared_ptr<iengine> graphics, const uint32 context = 0)
    {
        graphics->setViewport(_viewport, context);
        graphics->setRenderTargets(_renderTarget, _depthStencilTarget, context);
    }

    // snap from current targets in graphics
    void snap(const std::shared_ptr<iengine> graphics, const uint32 context = 0)
    {
        graphics->getViewport(&_viewport, context);
        _renderTarget = graphics->getRenderTarget(context);
        _depthStencilTarget = graphics->getDepthStencilTarget(context);
    }

    baja::graphics::viewport viewport() { return _viewport; }
    std::shared_ptr<isurface> renderTarget() { return _renderTarget; }
    std::shared_ptr<isurface> depthStencilTarget() { return _depthStencilTarget; }

    void setViewport(const baja::graphics::viewport& viewport) { _viewport = viewport; }
    void setRenderTarget(const std::shared_ptr<isurface>& renderTarget) { _renderTarget = renderTarget; }
    void setDepthStencilTarget(const std::shared_ptr<isurface>& depthStencilTarget) { _depthStencilTarget = depthStencilTarget; }

private:
    void cleanup()
    {
        _renderTarget = nullptr;
        _depthStencilTarget = nullptr;
    }

private:
    baja::graphics::viewport _viewport;
    std::shared_ptr<g::isurface> _renderTarget;
    std::shared_ptr<g::isurface> _depthStencilTarget;
};

struct snap_render_target : public render_target
{
public:
    snap_render_target(const std::shared_ptr<iengine>& graphics, const uint32 context = 0) : _graphics(graphics), _context(context)
    {
        this->snap(graphics, context);
    }

    ~snap_render_target()
    {
        this->apply(_graphics.lock(), _context);
    }

private:
    std::weak_ptr<iengine> _graphics;
    uint32 _context;
};

}} // namespace baja::graphics